﻿using OpenTK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LDLib
{
    /// <summary>
    /// Transform class. Represents a transformation that consists of
    /// location, orientation and scale.
    /// </summary>
    public class Transform
    {
        /// <summary>
        /// Location
        /// </summary>
        public Vector3 Location { get; set; }

        /// <summary>
        /// Rotation
        /// </summary>
        public Quaternion Rotation { get; set; }

        /// <summary>
        /// Scale
        /// </summary>
        public Vector3 Scale { get; set; }

        /// <summary>
        /// Constructs a new transform
        /// </summary>
        public Transform()
        {
            this.Location = Vector3.Zero;
            this.Rotation = Quaternion.Identity;
            this.Scale = Vector3.One;
        }

        /// <summary>
        /// Gets or sets the rotation in euler angles
        /// </summary>
        public Vector3 EulerAngles
        {
            get { return MathTools.ToEulerAngles(Rotation); }
            set { Rotation = MathTools.FromEulerAngles(value); }
        }

        /// <summary>
        /// Gets or sets the transformation matrix
        /// </summary>
        public Matrix4 Matrix
        {
            get
            {
                return Matrix4.Scale(Scale) * Matrix4.Rotate(Rotation) * Matrix4.CreateTranslation(Location);
            }
            set
            {
                Vector3 t, s;
                Quaternion r;
                MathTools.Decompose(ref value, out t, out r, out s);
                this.Location = t;
                this.Scale = s;
                this.Rotation = r;
            }
        }

        /// <summary>
        /// Gets a world transformation based on parent and child transformations
        /// </summary>
        /// <param name="parent">Parent transformation</param>
        /// <param name="child">Child transformation</param>
        /// <param name="result">Resulting world transformation</param>
        public static Transform GetWorldTransform(Transform parent, Transform child)
        {
            Transform result = new Transform();
            result.Location = Vector3.Transform(child.Location, Matrix4.Rotate(parent.Rotation));
            result.Location = Vector3.Multiply(result.Location, parent.Scale) + parent.Location;
            result.Rotation = parent.Rotation * child.Rotation;
            result.Scale = Vector3.Multiply(parent.Scale, child.Scale);
            return result;
        }
    }
}
